package solutions.ferpa.ztest.intf;

import br.com.telescope.adsrt.dom.DomId;
import br.com.telescope.adsrt.dom.DomOpcao;
import br.com.telescope.adsrt.dom.DomSelectionCheck;
import br.com.telescope.adsrt.dom.DomText;
import br.com.telescope.adsrt.dom.DomUpper;
import br.com.telescope.adsrt.lib.*;
import br.com.telescope.adsrt.lib.AdsException;
import br.com.telescope.adsrt.lib.Field;
import br.com.telescope.adsrt.lib.Form;
import br.com.telescope.sql.ModelQuery;
import br.com.telescope.t2.ModuleNavigator;
import br.com.telescope.t2.ServiceModel;
import br.com.telescope.t2.ServiceNavigation;
import br.com.telescope.t2.ServiceUrlManager;
import br.com.telescope.t2.exception.ApplicationRuntimeException;
import br.com.telescope.t2.exception.UnexpectedException;
import br.com.telescope.t2.feature.CustomActionFeature;
import br.com.telescope.t2.feature.CustomFeature;
import br.com.telescope.t2.feature.DeleteFeature;
import br.com.telescope.t2.feature.ListFeature;
import br.com.telescope.t2.feature.LookupFeature;
import br.com.telescope.t2.feature.MethodFeature;
import br.com.telescope.t2.feature.MultiRowInsertFeature;
import br.com.telescope.t2.feature.MultiRowUpdateFeature;
import br.com.telescope.t2.feature.QueryFeature;
import br.com.telescope.util.ObjectUtil;
import java.util.ArrayList;
import java.util.List;
import solutions.ferpa.ztest.ent.*;

/**
 * Cadastro das interfaces de uma função.
 * <p>
 * Interface de usuário chamada utilizada no contexto de uma função 
 * específica que permite estabelecer quais as interfaces que a mesma tem 
 * acesso, bem como as respectivas operações e recursos permitidos.
 * <P>
 * Ao ser aberta a partir da manutenção da funções, apresenta uma lista 
 * de todas as interfaces que esta função tem permissão de acessar, bem 
 * como as respectivas operações permitidas na mesma.
 * <P>
 * O usuário pode alterar as operações, excluir uma interface inteira, 
 * bem como incluir uma nova interface e informar as operações permitidas 
 * ma mesma.
 * <P>
 * 
 * <P>
 * 
 * <P>
 * Telescope origin: RTSYSINF.CAD_FUNCAO_INTERFACE
 * <P>
 * Base entity: RTSYSINF.INTERFACES_FUNCOES
 * <P>
 * @author TELESCOPE - Build task T2 Web Interface Generator
 * <P>
 * @version 0.1
 */
public class CadFuncaoInterface extends ServiceModel {
    
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    public static final String GLOBAL_NAME = "RTSYSINF.CAD_FUNCAO_INTERFACE";
    
    @Override
    public String globalName() {
        return GLOBAL_NAME;
    }
    
    {
        setTitle("Cadastro das interfaces de uma função");
    }
    
    protected EntInterfacesFuncoes intfun;
    protected EntInterfacesSistemas intsis;
    protected EntInterfacesFuncoes rec; // NEED_TJW1_COMPATIBILITY
    
    // Service parameters
    private DomId pFuncaoId;
    
    // Record items
    private DomId aId;
    private DomId aFuncaoId;
    private DomOpcao aInterfaceId;
    private DomUpper aNome;
    private DomText aTitulo;
    private DomText aOperacoesList;
    private DomSelectionCheck aOperacoes;
    private DomSelectionCheck aUnInterfaces;
    
    // Query items
    private DomText qTitulo;
    private DomUpper qNome;
    
    @Override
    public String getBaseSql() {
        return "select INTFUN.*"
                + " , INTSIS.NOME as NOME"
                + " , INTSIS.TITULO as TITULO"
                + " , INTSIS.ID as Z_INTSIS_ID"
                + " from INTERFACES_FUNCOES INTFUN"
                + " join INTERFACES_SISTEMAS INTSIS on INTSIS.ID = INTFUN.INTERFACE_ID";
    }
    
    @Override
    public void initAttributes() {
        
        aId = new DomId();
        aId.context(ctx).name("ID").label("Id");
        
        aFuncaoId = new DomId();
        aFuncaoId.context(ctx).name("FUNCAO_ID").label("Função");
        
        aInterfaceId = new DomOpcao();
        aInterfaceId.context(ctx).name("INTERFACE_ID").label("Interface").group(true);
        
        aNome = new DomUpper();
        aNome.context(ctx).name("NOME").label("Interface");
        aNome.setListOfValuesQuery(createQuery()
                .select("*")
                .from("(SELECT NOME as valor"
                + " , NOME as pesquisar"
                + " , NOME as descricao"
                + " from INTERFACES_SISTEMAS INTSIS)", "q"));
        aNome.setAutocompleteLength(1);
        
        aTitulo = new DomText();
        aTitulo.context(ctx).name("TITULO").label("Título");
        aTitulo.setListOfValuesQuery(createQuery()
                .select("*")
                .from("(SELECT TITULO as valor"
                + " , TITULO as pesquisar"
                + " , TITULO as descricao"
                + " from INTERFACES_SISTEMAS INTSIS)", "q"));
        aTitulo.setAutocompleteLength(1);
        
        aOperacoesList = new DomText();
        aOperacoesList.context(ctx).name("OPERACOES_LIST").label("Operações").unbound(true);
        
        aOperacoes = new DomSelectionCheck();
        aOperacoes.context(ctx).name("OPERACOES").label("Operações").width(20).unbound(true);
        
        aUnInterfaces = new DomSelectionCheck();
        aUnInterfaces.context(ctx).name("UN_INTERFACES").label("Interfaces").unbound(true);
        
        
        qTitulo = new DomText();
        qTitulo.context(ctx).name("TITULO").label("Título");
        qTitulo.setListOfValuesQuery(createQuery()
                .select("*")
                .from("(SELECT TITULO as valor"
                + " , TITULO as pesquisar"
                + " , TITULO as descricao"
                + " from INTERFACES_SISTEMAS INTSIS)", "q"));
        qTitulo.setAutocompleteLength(1);
        
        qNome = new DomUpper();
        qNome.context(ctx).name("NOME").label("Interface");
        qNome.setListOfValuesQuery(createQuery()
                .select("*")
                .from("(SELECT NOME as valor"
                + " , NOME as pesquisar"
                + " , NOME as descricao"
                + " from INTERFACES_SISTEMAS INTSIS)", "q"));
        qNome.setAutocompleteLength(1);
    }
    
    @Override
    public void initParameters() {
        pFuncaoId = new DomId(ctx, "FUNCAO_ID", "Função");
        pFuncaoId.setValue(ctx.getParameter("P_FUNCAO_ID"));
        if (pFuncaoId.isNotNull()) {
            aFuncaoId.setValue(pFuncaoId.getValue());
        }
    }
    
    @Override
    public List<Field> getParameters() {
        if (allParameters == null) {
            allParameters = new ArrayList<Field>();
            allParameters.add(pFuncaoId);
        }
        return allParameters;
    }
    
    @Override
    public void copyBindParameters() {
        EntInterfacesFuncoes record = getRecord();
        if (pFuncaoId.isNotNull()) {
            record.setFuncaoId(pFuncaoId.getValue());
        }
    }
    
    @Override
    public void retrieveBindParameters() {
        pFuncaoId.setValue(getRecord().valueOfFuncaoId());
    }
    
    @Override
    public String getQueryPkColumn() {
        return "INTFUN.ID";
    }
    
    @Override
    public void setId(String value) {
        this.aId.setValue(value);
    }
    
    @Override
    public EntInterfacesFuncoes getRecord() {
        if (intfun == null) {
            intfun = new EntInterfacesFuncoes(ctx);
            rec = intfun;
        }
        return this.intfun;
    }
    
    @Override
    public String getContextName() {
        return aNome.toText();
    }
    
    @Override
    public String getDefaultOrderBy() {
        return "NOME, TITULO";
    }
    
    @Override
    public void translateInsertFks(Form form) {
        ModelQuery query;
        
        // INTERFACE_ID
        try {
            if (form.hasFields("NOME")) {
                query = createQuery()
                        .select("INTSIS.ID")
                        .from("INTERFACES_SISTEMAS", "INTSIS")
                        .filter("INTSIS.NOME", form.get("NOME"))
                        ;
                intfun.setInterfaceId(ObjectUtil.toLong(translateFk(query)));
            }
        } catch (AdsException ex) {
            throw new RuntimeException(ex);
        }
    }
    
    /**
     * Popula os valores de unbounds
     */
    @Override
    public void calculateUnboundValues() {
        try {
            aOperacoesList.setValue(listaOperacoes());
        } catch (AdsException ex) {
            throw new UnexpectedException("running inference rules", ex);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="QUERY">
    public class FQuery extends QueryFeature {
        
        @Override
        public void initForm() {
            addField(qNome, "opt");
            addField(qTitulo, "opt");
        }
        
        {
            setFeatureName("QUERY");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="UPDATE">
    public class FUpdate extends MultiRowUpdateFeature {
        
        @Override
        public void initForm() {
            aNome.setEditable(false);
            addField(aNome, "view");
            aTitulo.setEditable(false);
            addField(aTitulo, "view");
            addField(aOperacoes, "opt");
        }
        
        @Override
        public void onAction() {
            addSubmit(getFeature("CUSTOM")).label("Novos").icon("wizard.gif");
        }
        
        @Override
        public void posUpdate() {
            try {
                salvarOperacoes();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        @Override
        public void preRecord() {
            try {
                popularOperacoesUpdate();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        {
            setFeatureName("UPDATE");
            setPrimary(false);
            setRows(50);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="LIST">
    public class FList extends ListFeature {
        
        @Override
        public void initForm() {
            addField(aNome, "view");
            addField(aTitulo, "view");
            addField(aOperacoesList, "view");
        }
        
        @Override
        public void onAction() {
            addSubmit(getFeature("CUSTOM")).label("Novos").icon("wizard.gif");
            addSubmit(getFeature("INCLUSAO_MENU")).label("Inclusão pelo menu").icon("wizard.gif");
        }
        
        {
            setFeatureName("LIST");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="INSERT">
    public class FInsert extends MultiRowInsertFeature {
        
        @Override
        public void initForm() {
            aNome.setOptional(false);
            addField(aNome, "rqd");
            aTitulo.setEditable(false);
            addField(aTitulo, "view");
            addField(aOperacoes, "opt");
            registerEvent("ON_CHANGE", "NOME", "popularOperacoesInclusao");
        }
        
        @Override
        public void posInsert() {
            try {
                salvarOperacoes();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        @Override
        public void preDisplay() {
            try {
                popularInterfaces();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        {
            setFeatureName("INSERT");
            setPrimary(false);
            setRows(10);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="DELETE">
    public class FDelete extends DeleteFeature {
        
        @Override
        public void initForm() {
            addField(aNome, "view");
            addField(aTitulo, "view");
        }
        
        {
            setFeatureName("DELETE");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="CUSTOM">
    public class FCustom extends CustomFeature {
        
        @Override
        public void initForm() {
            addField(aUnInterfaces, "opt");
        }
        
        @Override
        public void preDisplay() {
            try {
                montarInterfaceCustom();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        @Override
        public void onAction() {
            addSubmit(getFeature("SALVAR_INTERFACES_SELECIONADAS")).label("Salvar interfaces selecionadas").icon("salvar.gif");
        }
        
        {
            setFeatureName("CUSTOM");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="INCLUSAO_MENU">
    public class FInclusaoMenu extends CustomActionFeature {
        
        @Override
        public void initForm() {
            addField(aUnInterfaces, "opt");
        }
        
        @Override
        public void preDisplay() {
            try {
                montarTelaInclusaoPeloMenu();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        @Override
        public void execute() {
            try {
                inclusaoMenu();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        {
            setFeatureName("INCLUSAO_MENU");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="SALVAR_INTERFACES_SELECIONADAS">
    public class FSalvarInterfacesSelecionadas extends MethodFeature {
        
        @Override
        public void run() {
            preRun();
            try {
                salvarInterfacesSelecionadas();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        {
            setFeatureName("SALVAR_INTERFACES_SELECIONADAS");
            setTitle("Salvar interfaces selecionadas");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="NOME_LOOKUP">
    public class FNomeLookup extends LookupFeature {
        
        @Override
        public void initForm() {
            aNome.setEditable(true);
            addField(aNome, "opt");
            aTitulo.setEditable(false);
            addField(aTitulo, "view");
        }
        
        @Override
        public ModelQuery getLookupQuery() {
            return createQuery()
                    .select("INTSIS.NOME as NOME")
                    .select("INTSIS.TITULO as TITULO")
                    .from("INTERFACES_SISTEMAS", "INTSIS")
                    ;
        }
        
        {
            setFeatureName("NOME_LOOKUP");
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="initFeatures">
    
    @Override
    protected void initFeatures() {
        addFeature(new FQuery());
        addFeature(new FUpdate());
        addFeature(new FList());
        addFeature(new FInsert());
        addFeature(new FDelete());
        addFeature(new FCustom());
        addFeature(new FInclusaoMenu());
        addFeature(new FSalvarInterfacesSelecionadas());
        addFeature(new FNomeLookup());
        super.initFeatures();
    }
    
    @Override
    public String getDefaultFeature() {
        return "QUERY";
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Getters and Setters">
    
    @Override
    public Long getId() {
        return aId.getValue();
    }
    
    public void setId(Long value) {
        this.aId.setValue(value);
    }
    
    public Long getFuncaoId() {
        return aFuncaoId.getValue();
    }
    
    public void setFuncaoId(Long value) {
        this.aFuncaoId.setValue(value);
    }
    
    public String getInterfaceId() {
        return aInterfaceId.getValue();
    }
    
    public void setInterfaceId(String value) {
        this.aInterfaceId.setValue(value);
    }
    
    public String getNome() {
        return aNome.getValue();
    }
    
    public void setNome(String value) {
        this.aNome.setValue(value);
    }
    
    public String getTitulo() {
        return aTitulo.getValue();
    }
    
    public void setTitulo(String value) {
        this.aTitulo.setValue(value);
    }
    
    public String getOperacoesList() {
        return aOperacoesList.getValue();
    }
    
    public void setOperacoesList(String value) {
        this.aOperacoesList.setValue(value);
    }
    
    public String getOperacoes() {
        return aOperacoes.getValue();
    }
    
    public void setOperacoes(String value) {
        this.aOperacoes.setValue(value);
    }
    
    public String getUnInterfaces() {
        return aUnInterfaces.getValue();
    }
    
    public void setUnInterfaces(String value) {
        this.aUnInterfaces.setValue(value);
    }
    public String getQueryNome() {
        return qNome.getQueryValue();
    }
    
    public void setQueryNome(String value) {
        this.qNome.setQueryValue(value);
    }
    public String getQueryTitulo() {
        return qTitulo.getQueryValue();
    }
    
    public void setQueryTitulo(String value) {
        this.qTitulo.setQueryValue(value);
    }
    
    public Long getParameterFuncaoId() {
        return pFuncaoId.getValue();
    }
    
    public void setParameterFuncaoId(Long value) {
        pFuncaoId.setValue(value);
        aFuncaoId.setValue(value);
    }
    // </editor-fold>
    
    /**
     * null.
     */
    public void inclusaoMenu() throws AdsException {
        // <user-code id="12537965" parentId="12537959" hashcode="-15a07dc1" length="791">
        aUnInterfaces.getHtmlParameter(ads);
        String[] list = aUnInterfaces.getValue().split(",");
        
        EntOperacoesSistemas os = new EntOperacoesSistemas(ads);
        EntOperacoesFuncoes of = new EntOperacoesFuncoes(ads);
        
        for (String sid: list) {
            if (sid.length() > 0) {
                rec.setInterfaceId( sid );
                rec.setFuncaoId( pFuncaoId.getValue() );
                rec.ins();
                os.find("select id" +
                    " from operacoes_sistemas" +
                    " where interface_id = ?");
                os.sqlSetLong(1, rec.valueOfInterfaceId());
                while (os.next()) {
                    of.nullify();
                    of.setFuncaoId(rec.valueOfFuncaoId());
                    of.setOperacaoId(os.valueOfId());
                    of.ins();
                }
                os.close();
                rec.nullify();
            }
        }
        doList();
        // </user-code>
    }
    
    /**
     * Criar acessos default.
     * <p>
     * Na inclusão de uma interface, todas as operações são incluídas por 
     * default.
     * <P>
     */
    private void criarAcessosDefault() throws AdsException {
        // <user-code id="806814" parentId="752640" hashcode="-67708bef" length="394">
        EntOperacoesSistemas os = new EntOperacoesSistemas(ads);
        os.find("select id" +
                " from operacoes_sistemas" +
                " where interface_id = ?");
        os.sqlSetLong(1, rec.valueOfInterfaceId());
        while (os.next()) {
            EntOperacoesFuncoes of = new EntOperacoesFuncoes(ads);
            of.setFuncaoId(rec.valueOfFuncaoId());
            of.setOperacaoId(os.valueOfId());
            of.ins();
        }
        os.close();
        // </user-code>
    }
    
    /**
     * Declarações.
     */
    // <user-code id="12538452" parentId="12538451" hashcode="-5eeff337" length="2939">
    private ServiceUrlManager urlManager;
    
    private ServiceUrlManager getUrlManager() {
        if (urlManager == null) {
            urlManager = ServiceUrlManager.getInstance();
        }
        return urlManager;
    }
    
    private void incluir( Entity i, String menu, int nivel ) throws AdsException {
        if (i instanceof EntMenus) {
    
            EntMenus k = (EntMenus)i;
    
            EntItensMenus itens = new EntItensMenus(ctx);
            itens.filterBy().equal(itens.getMenuId(), k.valueOfId() );
            itens.orderBy().asc(itens.getSequencia());
            while (itens.next()) {
                String xMenu = menu + "." + itens.valueOfTitulo();
                if (itens.getSubMenuId().isNotNull()) {
                    incluir(itens.findSubMenu(), xMenu, nivel+1);
                } else if (itens.getInterfaceId().isNotNull()) {
                    incluir(itens.findInterface(), xMenu, nivel+1);
                }
            }
        } else if (i instanceof EntInterfacesSistemas) {
            EntInterfacesSistemas k = (EntInterfacesSistemas)i;
            if (k.getTipoRegistro().in("I")) {
                // Nada
            } else if (k.getTipoRegistro().in("R")) {
                // Nada
            } else {
                String uri = getUrlManager().getUriForService(k.valueOfNome());
    
                
                String className =  this.getClass().getPackage().getName() + "." + uri.trim();
                Class<ServiceModel> tt = null;
                ServiceModel temp=null;
                try {
                    tt = (Class<ServiceModel>) Class.forName(className);
                    temp = tt.newInstance();
                    if (temp.getDefaultModuleNavigator()!=null) {
                        ModuleNavigator module = temp.getDefaultModuleNavigator();
                        int nn = 0;
                        for (ServiceNavigation x:module.getGuides()) {
                            EntInterfacesSistemas tmp = new EntInterfacesSistemas(ctx);
                            String modClassName =  this.getClass().getPackage().getName() + "." + x.getDestination().getSimpleName();
                            Class<ServiceModel> tx = null;
                            ServiceModel ttemp=null;
                            try {
                                tx = (Class<ServiceModel>) Class.forName(modClassName);
                                ttemp = tx.newInstance();
                                tmp.findByNome(ttemp.globalName());
                            } catch (Exception exx) {
                                throw new AdsException(exx);
                            }
    
    
                            aUnInterfaces.addOption(tmp.getId().toString(), menu + ":" + tmp.valueOfTitulo() + "[" + x.getLabel() + "]", false);
                        }
                    } else {
                        aUnInterfaces.addOption(k.getId().toString(), menu + " -> " + uri, false);
                    }
    
                } catch (Exception ex) {
                    throw new AdsException(ex);
                }
    
            }
        }
    
    }
    // </user-code>
    
    /**
     * Lista de operações.
     * <p>
     * Retorna uma lista das operações que a função tem acesso nesta 
     * interface.
     * <P>
     */
    private String listaOperacoes() throws AdsException {
        // <user-code id="806820" parentId="752635" hashcode="-14854398" length="562">
        StringBuilder str = new StringBuilder();
        EntOperacoesFuncoes of = new EntOperacoesFuncoes(ads);
        of.find("select opfu.id" +
                " from operacoes_funcoes opfu" +
                " join operacoes_sistemas os on os.id=opfu.operacao_id" +
                " where opfu.funcao_id = " + rec.valueOfFuncaoId() +
                " and os.interface_id = " + rec.valueOfInterfaceId() +
                " order by os.titulo");
        while (of.next()) {
            if (str.length()>0) str.append(", ");
            str.append(of.findOperacao().valueOfTitulo().toLowerCase());
        }
        of.close();
        return str.toString();
        // </user-code>
    }
    
    /**
     * Montar interface custom.
     * <p>
     * Montar a interface custom apresentando todos as interfaces que estão 
     * ainda disponíveis para esta função
     */
    private void montarInterfaceCustom() throws AdsException {
        // <user-code id="806815" parentId="752662" hashcode="7b1a2c39" length="503">
        //showModuleGuide();
        aUnInterfaces.addSqlOptions("select distinct i.id, i.nome || ' - ' || i.titulo,null" +
                " from interfaces_sistemas i" +
                " join operacoes_sistemas os on i.id=os.interface_id" +
                " where os.politica_acesso = 'R'" +
                " and not exists (" +
                "    select 1" +
                "    from interfaces_funcoes" +
                "    where interface_id=i.id and funcao_id=" + pFuncaoId.getValue() +
                " )" +
                " order by i.nome || ' - ' || i.titulo");
        // </user-code>
    }
    
    /**
     * Montar tela de inclusão pelo menu.
     */
    private void montarTelaInclusaoPeloMenu() throws AdsException {
        // <user-code id="12537969" parentId="12537967" hashcode="-1bebc676" length="337">
        // import br.com.telescope.t2.ModuleNavigator;
        // import br.com.telescope.t2.ServiceModel;
        // import br.com.telescope.t2.ServiceNavigation;
        // import br.com.telescope.t2.ServiceUrlManager;
        
        EntMenus menu = new EntMenus(ctx);
        menu.findByMenu(ctx.getPreference("RT.MENU.TOP_MENUS"));
        String tmpMenu = "";
        incluir(menu, tmpMenu, 0);
        // </user-code>
    }
    
    /**
     * Popular interfaces a incluir.
     * <p>
     * Popula as opções de interfaces que podem ser usadas na inclusão 
     * (apenas as interfaces não públicas e que ainda não foram inseridas)
     * <P>
     */
    private void popularInterfaces() throws AdsException {
        // <user-code id="806816" parentId="752638" hashcode="-70fc25e4" length="475">
        aInterfaceId.addSqlOptions("select distinct i.id, i.nome || ' - ' || i.titulo" +
                " from interfaces_sistemas i" +
                " join operacoes_sistemas os on i.id=os.interface_id" +
                " where os.politica_acesso = 'R'" +
                " and not exists (" +
                "    select 1" +
                "    from interfaces_funcoes" +
                "    where interface_id=i.id and funcao_id=" + pFuncaoId.getValue() +
                " )" +
                " order by i.nome || ' - ' || i.titulo");
        // </user-code>
    }
    
    /**
     * Popular operacoes para inclusão.
     * <p>
     * Popula as operações disponíveis existentes para uma determinada 
     * interface informada.
     */
    public void popularOperacoesInclusao() throws AdsException {
        // <user-code id="866392" parentId="866390" hashcode="-3f2ced3a" length="692">
        EntInterfacesSistemas is = new EntInterfacesSistemas(ctx);
        try {
            is.findByNome(aNome.getValue());
            aOperacoes.nullify();
            aOperacoes.clearOptions();
            
            EntOperacoesSistemas sis = new EntOperacoesSistemas(ctx);
            sis.filterBy()
                    .equal(sis.getInterfaceId(), is.valueOfId());
            sis.orderBy(sis.getTitulo());
            
            StringBuilder out = new StringBuilder(100);
            while (sis.next()) {
                if (out.length() > 0) out.append(",");
                out.append(sis.valueOfId());
                aOperacoes.addOption(sis.valueOfId().toString(), sis.valueOfTitulo());
            }
            aOperacoes.setValue(out.toString());
            
        } catch (RecordNotFoundException ignore) {}
        // </user-code>
    }
    
    /**
     * Popular operações para update.
     * <p>
     * Monta as opções de operações existentes para a interface informada.
     * <P>
     * Na implementação Java/j2ee, retorna uma string representante um JSON 
     * com o array de opções e indicando quais são habilitadas.
     * <P>
     */
    public void popularOperacoesUpdate() throws AdsException {
        // <user-code id="752631" parentId="752630" hashcode="-634b3ef3" length="746">
        aOperacoes.clearOptions();
        aOperacoes.addSqlOptions("select id," +
                " titulo, null" +
                " from operacoes_sistemas" +
                " where interface_id = " + rec.valueOfInterfaceId() +
                " order by titulo");
        StringBuilder str = new StringBuilder();
        EntOperacoesFuncoes of = new EntOperacoesFuncoes(ads);
        of.find("select opfu.id" +
                " from operacoes_funcoes opfu" +
                " join operacoes_sistemas os on os.id=opfu.operacao_id" +
                " where opfu.funcao_id = " + rec.valueOfFuncaoId() +
                " and os.interface_id = " + rec.valueOfInterfaceId());
        while (of.next()) {
            if (str.length()>0) str.append(",");
            str.append(of.valueOfOperacaoId());
        }
        of.close();
        aOperacoes.setValue(str.toString());
        
        // </user-code>
    }
    
    /**
     * Salvar interfaces selecionadas.
     * <p>
     * Salvar as interfaces selecionadas
     */
    private void salvarInterfacesSelecionadas() throws AdsException {
        // <user-code id="752666" parentId="752664" hashcode="-15a07dc1" length="791">
        aUnInterfaces.getHtmlParameter(ads);
        String[] list = aUnInterfaces.getValue().split(",");
        
        EntOperacoesSistemas os = new EntOperacoesSistemas(ads);
        EntOperacoesFuncoes of = new EntOperacoesFuncoes(ads);
        
        for (String sid: list) {
            if (sid.length() > 0) {
                rec.setInterfaceId( sid );
                rec.setFuncaoId( pFuncaoId.getValue() );
                rec.ins();
                os.find("select id" +
                    " from operacoes_sistemas" +
                    " where interface_id = ?");
                os.sqlSetLong(1, rec.valueOfInterfaceId());
                while (os.next()) {
                    of.nullify();
                    of.setFuncaoId(rec.valueOfFuncaoId());
                    of.setOperacaoId(os.valueOfId());
                    of.ins();
                }
                os.close();
                rec.nullify();
            }
        }
        doList();
        // </user-code>
    }
    
    /**
     * Salvar operações.
     * <p>
     * Depois de alterar, atualiza os registros das operações que o usuário 
     * selecionou e exclui qualquer uma que não tenha sido selecionada.
     * <P>
     */
    private void salvarOperacoes() throws AdsException {
        // <user-code id="806819" parentId="752633" hashcode="45bfb6d8" length="987">
        EntOperacoesFuncoes of = new EntOperacoesFuncoes(ads);
        
        // Excluir os que não existem...
        of.del("select opfu.id" 
                + " from operacoes_funcoes opfu" 
                + " join operacoes_sistemas os on os.id = opfu.operacao_id" 
                + " where opfu.funcao_id = " + rec.valueOfFuncaoId() 
                + " and os.interface_id = " + rec.valueOfInterfaceId() 
                + (aOperacoes.isNotNull() 
                        ? " and opfu.operacao_id not in (" + aOperacoes.getValue() + ")"
                        : ""));
        
        // Incluir os que faltam ser incluidos
        String[] list = aOperacoes.getValue().split(",");
        for (String sid: list) {
            if (!sid.isEmpty()) {
                long operId = Long.parseLong(sid);
                try {
                    of.findByOperacaoIdFuncaoId(operId,rec.valueOfFuncaoId());
                } catch (RecordNotFoundException ex) {
                    of.nullify();
                    of.setFuncaoId(rec.valueOfFuncaoId());
                    of.setOperacaoId(operId);
                    of.ins();
                }
            }
        }
        // </user-code>
    }
    
    @Override
    public String getJsServiceFile() {
        return "ui/rtsysinf/cad_funcao_interface.js";
    }
}
